]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
fix "desktop"/"workspace" naming confusion
authorDan Winship <danw@src.gnome.org>
Thu, 4 Dec 2008 15:20:37 +0000 (15:20 +0000)
committerDan Winship <danw@src.gnome.org>
Thu, 4 Dec 2008 15:20:37 +0000 (15:20 +0000)
svn path=/trunk/; revision=116

js/ui/desktops.js [deleted file]
js/ui/overlay.js
js/ui/workspaces.js [new file with mode: 0644]

diff --git a/js/ui/desktops.js b/js/ui/desktops.js
deleted file mode 100644 (file)
index 3357b5f..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
-
-const Tweener = imports.tweener.tweener;
-const Clutter = imports.gi.Clutter;
-
-const Main = imports.ui.main;
-const Overlay = imports.ui.overlay;
-const Panel = imports.ui.panel;
-const Meta = imports.gi.Meta;
-const Shell = imports.gi.Shell;
-
-// Windows are slightly translucent in the overlay mode
-const WINDOW_OPACITY = 0.9 * 255;
-
-// Define a layout scheme for small window counts. For larger
-// counts we fall back to an algorithm. We need more schemes here
-// unless we have a really good algorithm.
-
-// Each triplet is [xCenter, yCenter, scale] where the scale
-// is relative to the width of the desktop.
-const POSITIONS = {
-        1: [[0.5, 0.5, 0.8]],
-        2: [[0.25, 0.5, 0.4], [0.75, 0.5, 0.4]],
-        3: [[0.25, 0.25, 0.33],  [0.75, 0.25, 0.33],  [0.5, 0.75, 0.33]],
-        4: [[0.25, 0.25, 0.33],   [0.75, 0.25, 0.33], [0.75, 0.75, 0.33], [0.25, 0.75, 0.33]],
-        5: [[0.165, 0.25, 0.28], [0.495, 0.25, 0.28], [0.825, 0.25, 0.28], [0.25, 0.75, 0.4], [0.75, 0.75, 0.4]]
-};
-
-// spacing between desktops
-const GRID_SPACING = 15;
-
-function Desktops(x, y, width, height) {
-    this._init(x, y, width, height);
-}
-
-Desktops.prototype = {
-    _init : function(x, y, width, height) {
-
-        this._group = new Clutter.Group();
-
-        this._x = x;
-        this._y = y;
-        this._width = width;
-        this._height = height;
-        this._workspaces = [];
-    },
-
-    show : function() {
-        let global = Shell.Global.get();
-
-        let windows = global.get_windows();
-        let activeWorkspace = global.screen.get_active_workspace_index();
-
-        // Create a group for each workspace (which lets us raise all of
-        // its clone windows together when the workspace is activated)
-        // and add the desktop windows
-        this._workspaces = [];
-        for (let w = 0; w < global.screen.n_workspaces; w++) {
-            this._workspaces[w] = new Clutter.Group();
-            this._group.add_actor(this._workspaces[w]);
-        }
-        this._createDesktopActors(windows);
-
-        // The workspaces will go into a grid that is either square,
-        // or else 1 cell wider than it is tall.
-        // FIXME: need to make the metacity internal layout agree with this!
-        let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
-        let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
-
-        let wsWidth = (this._width - (gridWidth - 1) * GRID_SPACING) / gridWidth;
-        let wsHeight = (this._height - (gridHeight - 1) * GRID_SPACING) / gridHeight;
-        let scale = wsWidth / global.screen_width;
-
-        // Position/scale the desktop windows and their children. This
-        // would be easier if we instead just positioned and scaled
-        // the entire workspace group, but if we do that then the
-        // windows of the active workspace will trace out a curved
-        // path as they move into place, which looks odd. Positioning
-        // everything independently lets us move them in a straight
-        // line.
-        for (let w = 0, x = this._x, y = this._y; w < this._workspaces.length; w++) {
-            let workspace = this._workspaces[w];
-            let desktop = workspace.get_nth_child(0);
-
-            if (w == activeWorkspace) {
-                // The currently-active workspace needs to
-                // slide/shrink into place
-                workspace.raise_top();
-                Tweener.addTween(desktop,
-                                 { x: x,
-                                   y: y,
-                                   scale_x: scale,
-                                   scale_y: scale,
-                                   time: Overlay.ANIMATION_TIME,
-                                   transition: "easeOutQuad"
-                                 });
-            } else {
-                // Other workspaces can start out in place; they'll be
-                // revealed as the active workspace shrinks
-                desktop.set_position(x, y);
-                desktop.set_scale(scale, scale);
-            }
-
-            // Now handle the rest of the windows in this workspace
-            let wswindows = windows.filter(function (win) { return win.get_workspace() == w; });
-
-            // Do the windows in reverse order so that the active
-            // actor ends up on top
-//            for (let i = wswindows.length - 1, windowIndex = 0; i >= 0; i--) {
-            for (let i = 0, windowIndex = 0; i < wswindows.length; i++) {
-                let win = wswindows[i];
-                if (win.get_window_type() == Meta.WindowType.DESKTOP ||
-                    win.is_override_redirect())
-                    continue;
-
-                this._createWindowClone(wswindows[i], this._workspaces[w],
-                                        x, y, scale,
-                                        wswindows.length - windowIndex - 1,
-                                        wswindows.length,
-                                        w == activeWorkspace);
-                windowIndex++;
-            }
-
-            x += (wsWidth + GRID_SPACING);
-            if (x >= this._x + this._width - GRID_SPACING) {
-                x = this._x;
-                y += wsHeight + GRID_SPACING;
-            }
-        }
-    },
-
-    hide : function() {
-        let global = Shell.Global.get();
-        let activeWorkspace = global.screen.get_active_workspace_index();
-
-        this._workspaces[activeWorkspace].raise_top();
-        let windows = this._workspaces[activeWorkspace].get_children();
-        for (let i = 0; i < windows.length; i++) {
-            Tweener.addTween(windows[i],
-                             { x: windows[i].orig_x || 0,
-                               y: windows[i].orig_y || 0,
-                               scale_x: 1.0,
-                               scale_y: 1.0,
-                               time: Overlay.ANIMATION_TIME,
-                               opacity: 255,
-                               transition: "easeOutQuad"
-                             });
-        }
-    },
-    
-    hideDone : function() {
-        for (let w = 0; w < this._workspaces.length; w++) {
-            this._workspaces[w].destroy();
-        }
-        this._workspaces = [];
-    },
-
-    _createDesktopActors : function(windows) {
-        let me = this;
-        let global = Shell.Global.get();
-
-        // Find the desktop window or windows
-        for (let i = 0; i < windows.length; i++) {
-            if (windows[i].get_window_type() != Meta.WindowType.DESKTOP)
-                continue;
-
-            if (windows[i].get_meta_window().is_on_all_workspaces()) {
-                for (let w = 0; w < this._workspaces.length; w++)
-                    this._workspaces[w].add_actor(this._cloneWindow(windows[i]));
-                break;
-            } else
-                this._workspaces[windows[i].get_workspace()].add_actor(this._cloneWindow(windows[i]));
-        }
-
-        // Create dummy desktops for workspaces that don't have
-        // desktop windows, and hook up button events on all desktops
-        for (let w = 0; w < this._workspaces.length; w++) {
-            if (this._workspaces[w].get_n_children() == 0)
-                this._workspaces[w].add_actor(this._createDesktopRectangle());
-
-            let workspace = global.screen.get_workspace_by_index(w);
-            this._workspaces[w].get_nth_child(0).connect(
-                "button-press-event",
-                function(clone, event) {
-                    workspace.activate(event.get_time());
-                    me._deactivate();
-                });
-        }
-    },
-
-    _cloneWindow : function(window) {
-        let w = new Clutter.CloneTexture({ parent_texture: window.get_texture(),
-                                           reactive: true,
-                                           x: window.x,
-                                           y: window.y });
-        w.orig_x = window.x;
-        w.orig_y = window.y;
-        return w;
-    },
-
-    _createDesktopRectangle : function() {
-        let global = Shell.Global.get();
-
-        // In the case when we have a desktop window from the file
-        // manager, its height is full-screen, i.e. it includes the
-        // height of the panel, so we should not subtract the height
-        // of the panel from global.screen_height here either to have
-        // them show up identically. We are also using (0,0)
-        // coordinates in both cases which makes the background window
-        // animate out from behind the panel.
-
-        return new Clutter.Rectangle({ color: global.stage.color,
-                                       reactive: true,
-                                       x: 0,
-                                       y: 0,
-                                       width: global.screen_width,
-                                       height: global.screen_height });
-    },
-
-    // windowIndex == 0 => top in stacking order
-    _computeWindowPosition : function(windowIndex, numberOfWindows) {
-        if (numberOfWindows in POSITIONS)
-            return POSITIONS[numberOfWindows][windowIndex];
-
-        // If we don't have a predefined scheme for this window count,
-        // overlap the windows along the diagonal of the desktop
-        // (improve this!)
-        let fraction = Math.sqrt(1/numberOfWindows);
-
-        // The top window goes at the lower right - this is different from the
-        // fixed position schemes where the windows are in "reading order"
-        // and the top window goes at the upper left.
-        let pos = (numberOfWindows - windowIndex - 1) / (numberOfWindows - 1);
-        let xCenter = (fraction / 2) + (1 - fraction) * pos;
-        let yCenter = xCenter;
-
-        return [xCenter, yCenter, fraction];
-    },
-
-    _createWindowClone : function(w, workspace, wsX, wsY, wsScale,
-                                  windowIndex, numberOfWindows, animate) {
-        let me = this;
-        let global = Shell.Global.get();
-
-        // We show the window using "clones" of the texture .. separate
-        // actors that mirror the original actors for the window. For
-        // animation purposes, it may be better to actually move the
-        // original actors about instead.
-
-        let clone = this._cloneWindow(w);
-        let [xCenter, yCenter, fraction] = this._computeWindowPosition(windowIndex, numberOfWindows);
-
-        let desiredSize = global.screen_width * fraction;
-
-        xCenter = wsX + wsScale * (xCenter * global.screen_width);
-        yCenter = wsY + wsScale * (yCenter * global.screen_height);
-
-        let size = clone.width;
-        if (clone.height > size)
-            size = clone.height;
-
-        // Never scale up
-        let scale = desiredSize / size;
-        if (scale > 1)
-            scale = 1;
-        scale *= wsScale;
-
-        workspace.add_actor(clone);
-
-        if (animate) {
-            Tweener.addTween(clone,
-                             { x: xCenter - 0.5 * scale * w.width,
-                               y: yCenter - 0.5 * scale * w.height,
-                               scale_x: scale,
-                               scale_y: scale,
-                               time: Overlay.ANIMATION_TIME,
-                               opacity: WINDOW_OPACITY,
-                               transition: "easeOutQuad"
-                             });
-        } else {
-            clone.set_position(xCenter - 0.5 * scale * w.width,
-                               yCenter - 0.5 * scale * w.height);
-            clone.set_scale(scale, scale);
-            clone.set_opacity(WINDOW_OPACITY);
-        }
-
-        clone.connect("button-press-event",
-                      function(clone, event) {
-                          clone.raise_top();
-                          me._activateWindow(w, event.get_time());
-                      });
-    },
-
-    _activateWindow : function(w, time) {
-        let global = Shell.Global.get();
-        let activeWorkspace = global.screen.get_active_workspace_index();
-        let windowWorkspace = w.get_workspace();
-
-        if (windowWorkspace != activeWorkspace) {
-            let workspace = global.screen.get_workspace_by_index(windowWorkspace);
-            workspace.activate_with_focus(w.get_meta_window(), time);
-        } else
-            w.get_meta_window().activate(time);
-        this._deactivate();
-    },
-
-    _deactivate : function() {
-        Main.hide_overlay();
-    }
-};
-
index ee8ad46dd150aa15f494a3602dc84fc3d8e24d18..fc0b36ba386de180cc067ba73c2feafc0a0cfc86 100644 (file)
@@ -7,7 +7,7 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
 
-const Desktops = imports.ui.desktops;
+const Workspaces = imports.ui.workspaces;
 const Main = imports.ui.main;
 const Panel = imports.ui.panel;
 const Meta = imports.gi.Meta;
@@ -28,8 +28,8 @@ SIDESHOW_TEXT_COLOR.from_pixel(0xffffffff);
 // Time for initial animation going into overlay mode
 const ANIMATION_TIME = 0.5;
 
-// How much to scale the desktop down by in overlay mode
-const DESKTOP_SCALE = 0.75;
+// How much of the screen the workspace grid takes up
+const WORKSPACE_GRID_SCALE = 0.75;
 
 function Sideshow(parent, width) {
     this._init(parent, width);
@@ -155,11 +155,12 @@ Overlay.prototype = {
         // TODO - recalculate everything when desktop size changes
         this._recalculateSize();
 
-        this._desktops = new Desktops.Desktops(this._desktopX, this._desktopY,
-                                               this._desktopWidth, this._desktopHeight);
-        this._group.add_actor(this._desktops._group);
+        this._workspaces = new Workspaces.Workspaces(
+            this._workspaceGridX, this._workspaceGridY,
+            this._workspaceGridWidth, this._workspaceGridHeight);
+        this._group.add_actor(this._workspaces._group);
 
-        this._sideshow = new Sideshow(this._group, this._desktopX - 10);
+        this._sideshow = new Sideshow(this._group, this._workspaceGridX - 10);
         this._sideshow.connect('activated', function(sideshow) {
             // TODO - have some sort of animation/effect while
             // transitioning to the new app.  We definitely need
@@ -173,12 +174,11 @@ Overlay.prototype = {
         let screenWidth = global.screen_width;
         let screenHeight = global.screen_height;
 
-        // The desktop windows are shown on top of a scaled down version of the
-        // desktop. This is positioned at the right side of the screen
-        this._desktopWidth = screenWidth * DESKTOP_SCALE;
-        this._desktopHeight = screenHeight * DESKTOP_SCALE;
-        this._desktopX = screenWidth - this._desktopWidth - 10;
-        this._desktopY = Panel.PANEL_HEIGHT + (screenHeight - this._desktopHeight - Panel.PANEL_HEIGHT) / 2;
+        // The area allocated for the workspace grid
+        this._workspaceGridWidth = screenWidth * WORKSPACE_GRID_SCALE;
+        this._workspaceGridHeight = screenHeight * WORKSPACE_GRID_SCALE;
+        this._workspaceGridX = screenWidth - this._workspaceGridWidth - 10;
+        this._workspaceGridY = Panel.PANEL_HEIGHT + (screenHeight - this._workspaceGridHeight - Panel.PANEL_HEIGHT) / 2;
     },
 
     show : function() {
@@ -192,8 +192,8 @@ Overlay.prototype = {
         this._recalculateSize();
 
         this._sideshow.show();
-        this._desktops.show();
-        this._desktops._group.raise_top();
+        this._workspaces.show();
+        this._workspaces._group.raise_top();
 
         // All the the actors in the window group are completely obscured,
         // hiding the group holding them while the overlay is displayed greatly
@@ -210,7 +210,7 @@ Overlay.prototype = {
         if (!this.visible)
             return;
 
-        this._desktops.hide();
+        this._workspaces.hide();
         this._sideshow.hide();
 
         // Dummy tween, just waiting for the workspace animation
@@ -228,7 +228,7 @@ Overlay.prototype = {
         global.window_group.show();
         this._group.lower_bottom();
         this._group.hide();
-        this._desktops.hideDone();
+        this._workspaces.hideDone();
     },
 
     _deactivate : function() {
diff --git a/js/ui/workspaces.js b/js/ui/workspaces.js
new file mode 100644 (file)
index 0000000..d2dfc40
--- /dev/null
@@ -0,0 +1,311 @@
+/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+
+const Tweener = imports.tweener.tweener;
+const Clutter = imports.gi.Clutter;
+
+const Main = imports.ui.main;
+const Overlay = imports.ui.overlay;
+const Panel = imports.ui.panel;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+
+// Windows are slightly translucent in the overlay mode
+const WINDOW_OPACITY = 0.9 * 255;
+
+// Define a layout scheme for small window counts. For larger
+// counts we fall back to an algorithm. We need more schemes here
+// unless we have a really good algorithm.
+
+// Each triplet is [xCenter, yCenter, scale] where the scale
+// is relative to the width of the workspace.
+const POSITIONS = {
+        1: [[0.5, 0.5, 0.8]],
+        2: [[0.25, 0.5, 0.4], [0.75, 0.5, 0.4]],
+        3: [[0.25, 0.25, 0.33],  [0.75, 0.25, 0.33],  [0.5, 0.75, 0.33]],
+        4: [[0.25, 0.25, 0.33],   [0.75, 0.25, 0.33], [0.75, 0.75, 0.33], [0.25, 0.75, 0.33]],
+        5: [[0.165, 0.25, 0.28], [0.495, 0.25, 0.28], [0.825, 0.25, 0.28], [0.25, 0.75, 0.4], [0.75, 0.75, 0.4]]
+};
+
+// spacing between workspaces
+const GRID_SPACING = 15;
+
+function Workspaces(x, y, width, height) {
+    this._init(x, y, width, height);
+}
+
+Workspaces.prototype = {
+    _init : function(x, y, width, height) {
+
+        this._group = new Clutter.Group();
+
+        this._x = x;
+        this._y = y;
+        this._width = width;
+        this._height = height;
+        this._workspaces = [];
+    },
+
+    show : function() {
+        let global = Shell.Global.get();
+
+        let windows = global.get_windows();
+        let activeWorkspace = global.screen.get_active_workspace_index();
+
+        // Create a group for each workspace (which lets us raise all of
+        // its clone windows together when the workspace is activated)
+        // and add the desktop windows
+        this._workspaces = [];
+        for (let w = 0; w < global.screen.n_workspaces; w++) {
+            this._workspaces[w] = new Clutter.Group();
+            this._group.add_actor(this._workspaces[w]);
+        }
+        this._createDesktopActors(windows);
+
+        // The workspaces will go into a grid that is either square,
+        // or else 1 cell wider than it is tall.
+        // FIXME: need to make the metacity internal layout agree with this!
+        let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
+        let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
+
+        let wsWidth = (this._width - (gridWidth - 1) * GRID_SPACING) / gridWidth;
+        let wsHeight = (this._height - (gridHeight - 1) * GRID_SPACING) / gridHeight;
+        let scale = wsWidth / global.screen_width;
+
+        // Position/scale the desktop windows and their children. This
+        // would be easier if we instead just positioned and scaled
+        // the entire workspace group, but if we do that then the
+        // windows of the active workspace will trace out a curved
+        // path as they move into place, which looks odd. Positioning
+        // everything independently lets us move them in a straight
+        // line.
+        for (let w = 0, x = this._x, y = this._y; w < this._workspaces.length; w++) {
+            let workspace = this._workspaces[w];
+            let desktop = workspace.get_nth_child(0);
+
+            if (w == activeWorkspace) {
+                // The currently-active workspace needs to
+                // slide/shrink into place
+                workspace.raise_top();
+                Tweener.addTween(desktop,
+                                 { x: x,
+                                   y: y,
+                                   scale_x: scale,
+                                   scale_y: scale,
+                                   time: Overlay.ANIMATION_TIME,
+                                   transition: "easeOutQuad"
+                                 });
+            } else {
+                // Other workspaces can start out in place; they'll be
+                // revealed as the active workspace shrinks
+                desktop.set_position(x, y);
+                desktop.set_scale(scale, scale);
+            }
+
+            // Now handle the rest of the windows in this workspace
+            let wswindows = windows.filter(function (win) { return win.get_workspace() == w; });
+
+            // Do the windows in reverse order so that the active
+            // actor ends up on top
+//            for (let i = wswindows.length - 1, windowIndex = 0; i >= 0; i--) {
+            for (let i = 0, windowIndex = 0; i < wswindows.length; i++) {
+                let win = wswindows[i];
+                if (win.get_window_type() == Meta.WindowType.DESKTOP ||
+                    win.is_override_redirect())
+                    continue;
+
+                this._createWindowClone(wswindows[i], this._workspaces[w],
+                                        x, y, scale,
+                                        wswindows.length - windowIndex - 1,
+                                        wswindows.length,
+                                        w == activeWorkspace);
+                windowIndex++;
+            }
+
+            x += (wsWidth + GRID_SPACING);
+            if (x >= this._x + this._width - GRID_SPACING) {
+                x = this._x;
+                y += wsHeight + GRID_SPACING;
+            }
+        }
+    },
+
+    hide : function() {
+        let global = Shell.Global.get();
+        let activeWorkspace = global.screen.get_active_workspace_index();
+
+        this._workspaces[activeWorkspace].raise_top();
+        let windows = this._workspaces[activeWorkspace].get_children();
+        for (let i = 0; i < windows.length; i++) {
+            Tweener.addTween(windows[i],
+                             { x: windows[i].orig_x || 0,
+                               y: windows[i].orig_y || 0,
+                               scale_x: 1.0,
+                               scale_y: 1.0,
+                               time: Overlay.ANIMATION_TIME,
+                               opacity: 255,
+                               transition: "easeOutQuad"
+                             });
+        }
+    },
+    
+    hideDone : function() {
+        for (let w = 0; w < this._workspaces.length; w++) {
+            this._workspaces[w].destroy();
+        }
+        this._workspaces = [];
+    },
+
+    _createDesktopActors : function(windows) {
+        let me = this;
+        let global = Shell.Global.get();
+
+        // Find the desktop window or windows
+        for (let i = 0; i < windows.length; i++) {
+            if (windows[i].get_window_type() != Meta.WindowType.DESKTOP)
+                continue;
+
+            if (windows[i].get_meta_window().is_on_all_workspaces()) {
+                for (let w = 0; w < this._workspaces.length; w++)
+                    this._workspaces[w].add_actor(this._cloneWindow(windows[i]));
+                break;
+            } else
+                this._workspaces[windows[i].get_workspace()].add_actor(this._cloneWindow(windows[i]));
+        }
+
+        // Create dummy desktops for workspaces that don't have
+        // desktop windows, and hook up button events on all desktops
+        for (let w = 0; w < this._workspaces.length; w++) {
+            if (this._workspaces[w].get_n_children() == 0)
+                this._workspaces[w].add_actor(this._createDesktopRectangle());
+
+            let workspace = global.screen.get_workspace_by_index(w);
+            this._workspaces[w].get_nth_child(0).connect(
+                "button-press-event",
+                function(clone, event) {
+                    workspace.activate(event.get_time());
+                    me._deactivate();
+                });
+        }
+    },
+
+    _cloneWindow : function(window) {
+        let w = new Clutter.CloneTexture({ parent_texture: window.get_texture(),
+                                           reactive: true,
+                                           x: window.x,
+                                           y: window.y });
+        w.orig_x = window.x;
+        w.orig_y = window.y;
+        return w;
+    },
+
+    _createDesktopRectangle : function() {
+        let global = Shell.Global.get();
+
+        // In the case when we have a desktop window from the file
+        // manager, its height is full-screen, i.e. it includes the
+        // height of the panel, so we should not subtract the height
+        // of the panel from global.screen_height here either to have
+        // them show up identically. We are also using (0,0)
+        // coordinates in both cases which makes the background window
+        // animate out from behind the panel.
+
+        return new Clutter.Rectangle({ color: global.stage.color,
+                                       reactive: true,
+                                       x: 0,
+                                       y: 0,
+                                       width: global.screen_width,
+                                       height: global.screen_height });
+    },
+
+    // windowIndex == 0 => top in stacking order
+    _computeWindowPosition : function(windowIndex, numberOfWindows) {
+        if (numberOfWindows in POSITIONS)
+            return POSITIONS[numberOfWindows][windowIndex];
+
+        // If we don't have a predefined scheme for this window count,
+        // overlap the windows along the diagonal of the workspace
+        // (improve this!)
+        let fraction = Math.sqrt(1/numberOfWindows);
+
+        // The top window goes at the lower right - this is different from the
+        // fixed position schemes where the windows are in "reading order"
+        // and the top window goes at the upper left.
+        let pos = (numberOfWindows - windowIndex - 1) / (numberOfWindows - 1);
+        let xCenter = (fraction / 2) + (1 - fraction) * pos;
+        let yCenter = xCenter;
+
+        return [xCenter, yCenter, fraction];
+    },
+
+    _createWindowClone : function(w, workspace, wsX, wsY, wsScale,
+                                  windowIndex, numberOfWindows, animate) {
+        let me = this;
+        let global = Shell.Global.get();
+
+        // We show the window using "clones" of the texture .. separate
+        // actors that mirror the original actors for the window. For
+        // animation purposes, it may be better to actually move the
+        // original actors about instead.
+
+        let clone = this._cloneWindow(w);
+        let [xCenter, yCenter, fraction] = this._computeWindowPosition(windowIndex, numberOfWindows);
+
+        let desiredSize = global.screen_width * fraction;
+
+        xCenter = wsX + wsScale * (xCenter * global.screen_width);
+        yCenter = wsY + wsScale * (yCenter * global.screen_height);
+
+        let size = clone.width;
+        if (clone.height > size)
+            size = clone.height;
+
+        // Never scale up
+        let scale = desiredSize / size;
+        if (scale > 1)
+            scale = 1;
+        scale *= wsScale;
+
+        workspace.add_actor(clone);
+
+        if (animate) {
+            Tweener.addTween(clone,
+                             { x: xCenter - 0.5 * scale * w.width,
+                               y: yCenter - 0.5 * scale * w.height,
+                               scale_x: scale,
+                               scale_y: scale,
+                               time: Overlay.ANIMATION_TIME,
+                               opacity: WINDOW_OPACITY,
+                               transition: "easeOutQuad"
+                             });
+        } else {
+            clone.set_position(xCenter - 0.5 * scale * w.width,
+                               yCenter - 0.5 * scale * w.height);
+            clone.set_scale(scale, scale);
+            clone.set_opacity(WINDOW_OPACITY);
+        }
+
+        clone.connect("button-press-event",
+                      function(clone, event) {
+                          clone.raise_top();
+                          me._activateWindow(w, event.get_time());
+                      });
+    },
+
+    _activateWindow : function(w, time) {
+        let global = Shell.Global.get();
+        let activeWorkspace = global.screen.get_active_workspace_index();
+        let windowWorkspace = w.get_workspace();
+
+        if (windowWorkspace != activeWorkspace) {
+            let workspace = global.screen.get_workspace_by_index(windowWorkspace);
+            workspace.activate_with_focus(w.get_meta_window(), time);
+        } else
+            w.get_meta_window().activate(time);
+        this._deactivate();
+    },
+
+    _deactivate : function() {
+        Main.hide_overlay();
+    }
+};
+